PÔhjalik juhend JavaScripti iteraatori protokolli mÔistmiseks ja rakendamiseks, mis vÔimaldab luua kohandatud iteraatoreid paremaks andmetöötluseks.
JavaScripti iteraatori protokolli ja kohandatud iteraatorite lahtimÔtestamine
JavaScripti iteraatori protokoll pakub standardiseeritud viisi andmestruktuuride lĂ€bimiseks. Selle protokolli mĂ”istmine annab arendajatele vĂ”imaluse tĂ”husalt töötada sisseehitatud itereeritavate objektidega, nagu massiivid ja sĂ”ned, ning luua oma kohandatud itereeritavaid objekte, mis on kohandatud spetsiifilistele andmestruktuuridele ja rakenduse nĂ”uetele. See juhend pakub pĂ”hjalikku ĂŒlevaadet iteraatori protokollist ja sellest, kuidas kohandatud iteraatoreid rakendada.
Mis on iteraatori protokoll?
Iteraatori protokoll mÀÀratleb, kuidas objekti saab itereerida, st kuidas selle elementidele jÀrjestikku juurde pÀÀseda. See koosneb kahest osast: itereeritavast protokollist ja iteraatori protokollist.
Itereeritav protokoll
Objekti peetakse itereeritavaks, kui sellel on meetod vÔtmega Symbol.iterator. See meetod peab tagastama objekti, mis vastab iteraatori protokollile.
Sisuliselt teab itereeritav objekt, kuidas enda jaoks iteraator luua.
Iteraatori protokoll
Iteraatori protokoll mÀÀratleb, kuidas vÀÀrtusi jadast kÀtte saada. Objekti peetakse iteraatoriks, kui sellel on next() meetod, mis tagastab objekti kahe omadusega:
value: JÀrgmine vÀÀrtus jadas.done: TÔevÀÀrtus, mis nÀitab, kas iteraator on jÔudnud jada lÔppu. Kuidoneontrue, vÔibvalueomaduse Àra jÀtta.
next() meetod on iteraatori protokolli tööhobune. Iga next() kutse liigutab iteraatorit edasi ja tagastab jada jÀrgmise vÀÀrtuse. Kui kÔik vÀÀrtused on tagastatud, tagastab next() objekti, mille done vÀÀrtuseks on seatud true.
Sisseehitatud itereeritavad objektid
JavaScript pakub mitmeid sisseehitatud andmestruktuure, mis on olemuselt itereeritavad. Nende hulka kuuluvad:
- Massiivid
- SÔned
- Mapid
- Setid
- Funktsiooni arguments objekt
- TypedArrays
Neid itereeritavaid objekte saab otse kasutada for...of tsĂŒkliga, laialilaotamise sĂŒntaksiga (...) ja muude konstruktsioonidega, mis tuginevad iteraatori protokollile.
NĂ€ide massiividega:
const myArray = ["apple", "banana", "cherry"];
for (const item of myArray) {
console.log(item); // VĂ€ljund: apple, banana, cherry
}
NÀide sÔnedega:
const myString = "Hello";
for (const char of myString) {
console.log(char); // VĂ€ljund: H, e, l, l, o
}
for...of tsĂŒkkel
for...of tsĂŒkkel on vĂ”imas konstruktsioon itereeritavate objektide lĂ€bimiseks. See tegeleb automaatselt iteraatori protokolli keerukustega, muutes jada vÀÀrtustele juurdepÀÀsu lihtsaks.
for...of tsĂŒkli sĂŒntaks on:
for (const element of iterable) {
// Kood, mis tÀidetakse iga elemendi jaoks
}
for...of tsĂŒkkel hangib iteraatori itereeritavast objektist (kasutades Symbol.iterator) ja kutsub korduvalt iteraatori next() meetodit, kuni done muutub true-ks. Iga iteratsiooni korral omistatakse element muutujale next() poolt tagastatud value omaduse vÀÀrtus.
Kohandatud iteraatorite loomine
Kuigi JavaScript pakub sisseehitatud itereeritavaid objekte, peitub iteraatori protokolli tÔeline jÔud vÔimes defineerida kohandatud iteraatoreid omaenda andmestruktuuride jaoks. See vÔimaldab teil kontrollida, kuidas teie andmeid lÀbitakse ja neile juurde pÀÀsetakse.
Kohandatud iteraatori loomiseks tehke jÀrgmist:
- Defineerige klass vÔi objekt, mis esindab teie kohandatud andmestruktuuri.
- Rakendage oma klassil vÔi objektil
Symbol.iteratormeetod. See meetod peaks tagastama iteraatori objekti. - Iteraatori objektil peab olema
next()meetod, mis tagastab objektivaluejadoneomadustega.
NĂ€ide: Iteraatori loomine lihtsa vahemiku jaoks
Loome klassi nimega Range, mis esindab arvude vahemikku. Rakendame iteraatori protokolli, et vÔimaldada vahemikus olevate arvude itereerimist.
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let currentValue = this.start;
const that = this; // PĂŒĂŒa 'this' kinni iteraatori objekti sees kasutamiseks
return {
next() {
if (currentValue <= that.end) {
return {
value: currentValue++,
done: false,
};
} else {
return {
value: undefined,
done: true,
};
}
},
};
}
}
const myRange = new Range(1, 5);
for (const number of myRange) {
console.log(number); // VĂ€ljund: 1, 2, 3, 4, 5
}
Selgitus:
Rangeklass vÔtab oma konstruktoris vastustartjaendvÀÀrtused.Symbol.iteratormeetod tagastab iteraatori objekti. Sellel iteraatori objektil on oma olek (currentValue) janext()meetod.next()meetod kontrollib, kascurrentValueon vahemikus. Kui on, tagastab see objekti, mille vÀÀrtus on praegune vÀÀrtus jadoneon seatudfalse-ks. Samuti suurendab seecurrentValuevÀÀrtust jÀrgmise iteratsiooni jaoks.- Kui
currentValueĂŒletabendvÀÀrtuse, tagastabnext()meetod objekti, milledoneon seatudtrue-ks. - Pange tĂ€hele
that = thiskasutamist. Kunanext()meetodit kutsutakse teises skoobis (for...oftsĂŒkli poolt), ei viitaksthisnext()seesRange'i instantsile. Selle lahendamiseks pĂŒĂŒamethisvÀÀrtuse (Range'i instantsi) kinni muutujassethatvĂ€ljaspoolnext()skoopi ja kasutame seejĂ€relthat-inext()sees.
NĂ€ide: Iteraatori loomine ahelloendi jaoks
Vaatleme teist nÀidet: iteraatori loomine ahelloendi andmestruktuuri jaoks. Ahelloend on sÔlmede jada, kus iga sÔlm sisaldab vÀÀrtust ja viidet (osutit) jÀrgmisele sÔlmele loendis. Loendi viimasel sÔlmel on viide nullile (vÔi undefined).
class LinkedListNode {
constructor(value, next = null) {
this.value = value;
this.next = next;
}
}
class LinkedList {
constructor() {
this.head = null;
}
append(value) {
const newNode = new LinkedListNode(value);
if (!this.head) {
this.head = newNode;
return;
}
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
[Symbol.iterator]() {
let current = this.head;
return {
next() {
if (current) {
const value = current.value;
current = current.next;
return {
value: value,
done: false
};
} else {
return {
value: undefined,
done: true
};
}
}
};
}
}
// NĂ€idiskasutus:
const myList = new LinkedList();
myList.append("London");
myList.append("Paris");
myList.append("Tokyo");
for (const city of myList) {
console.log(city); // VĂ€ljund: London, Paris, Tokyo
}
Selgitus:
LinkedListNodeklass esindab ĂŒhte sĂ”lme ahelloendis, salvestadesvalueja viite (next) jĂ€rgmisele sĂ”lmele.LinkedListklass esindab ahelloendit ennast. See sisaldabheadomadust, mis osutab loendi esimesele sĂ”lmele.append()meetod lisab uusi sĂ”lmi loendi lĂ”ppu.Symbol.iteratormeetod loob ja tagastab iteraatori objekti. See iteraator jĂ€lgib hetkel kĂŒlastatavat sĂ”lme (current).next()meetod kontrollib, kas on olemas praegune sĂ”lm (currentei ole null). Kui on, hangib see vÀÀrtuse praegusest sĂ”lmest, liigutabcurrentosuti jĂ€rgmisele sĂ”lmele ja tagastab objekti vÀÀrtusega jadone: false.- Kui
currentmuutub nulliks (mis tÀhendab, et oleme jÔudnud loendi lÔppu), tagastabnext()meetod objekti, milledoneontrue.
Generaatorfunktsioonid
Generaatorfunktsioonid pakuvad lĂŒhemat ja elegantsemat viisi iteraatorite loomiseks. Nad kasutavad yield vĂ”tmesĂ”na vÀÀrtuste tootmiseks vastavalt vajadusele.
Generaatorfunktsioon defineeritakse kasutades function* sĂŒntaksit.
NĂ€ide: Iteraatori loomine generaatorfunktsiooni abil
Kirjutame Range iteraatori ĂŒmber, kasutades generaatorfunktsiooni:
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
*[Symbol.iterator]() {
for (let i = this.start; i <= this.end; i++) {
yield i;
}
}
}
const myRange = new Range(1, 5);
for (const number of myRange) {
console.log(number); // VĂ€ljund: 1, 2, 3, 4, 5
}
Selgitus:
Symbol.iteratormeetod on nĂŒĂŒd generaatorfunktsioon (pange tĂ€hele*).- Generaatorfunktsiooni sees kasutame
for-tsĂŒklit, et itereerida ĂŒle arvude vahemiku. yieldvĂ”tmesĂ”na peatab generaatorfunktsiooni tĂ€itmise ja tagastab praeguse vÀÀrtuse (i). JĂ€rgmisel korral, kui iteraatorinext()meetodit kutsutakse, jĂ€tkub tĂ€itmine sealt, kus see pooleli jĂ€i (pĂ€rastyieldlauset).- Kui tsĂŒkkel lĂ”peb, tagastab generaatorfunktsioon kaudselt
{ value: undefined, done: true }, andes mÀrku iteratsiooni lÔpust.
Generaatorfunktsioonid lihtsustavad iteraatori loomist, tegeledes automaatselt next() meetodi ja done lipuga.
NĂ€ide: Fibonacci jada generaator
Veel ĂŒks suurepĂ€rane nĂ€ide generaatorfunktsioonide kasutamisest on Fibonacci jada genereerimine:
function* fibonacciSequence() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b]; // Destruktureeriv omistamine samaaegseks uuendamiseks
}
}
const fibonacci = fibonacciSequence();
for (let i = 0; i < 10; i++) {
console.log(fibonacci.next().value); // VĂ€ljund: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
}
Selgitus:
fibonacciSequencefunktsioon on generaatorfunktsioon.- See lÀhtestab kaks muutujat,
ajab, Fibonacci jada kahe esimese arvuga (0 ja 1). while (true)tsĂŒkkel loob lĂ”pmatu jada.yield alause toodabapraeguse vÀÀrtuse.[a, b] = [b, a + b]lause uuendab samaaegseltajabvÀÀrtusi jada kahe jĂ€rgmise arvuga, kasutades destruktureerivat omistamist.fibonacci.next().valueavaldis hangib generaatorist jĂ€rgmise vÀÀrtuse. Kuna generaator on lĂ”pmatu, peate kontrollima, mitu vÀÀrtust te sellest eraldate. Selles nĂ€ites eraldame esimesed 10 vÀÀrtust.
Iteraatori protokolli kasutamise eelised
- Standardiseerimine: Iteraatori protokoll pakub ĂŒhtset viisi erinevate andmestruktuuride itereerimiseks.
- Paindlikkus: Saate defineerida kohandatud iteraatoreid, mis on kohandatud teie spetsiifilistele vajadustele.
- Loetavus:
for...oftsĂŒkkel muudab iteratsioonikoodi loetavamaks ja lĂŒhemaks. - TĂ”husus: Iteraatorid vĂ”ivad olla laisad, mis tĂ€hendab, et nad genereerivad vÀÀrtusi ainult siis, kui neid vajatakse, mis vĂ”ib parandada suurte andmehulkade puhul jĂ”udlust. NĂ€iteks ĂŒlaltoodud Fibonacci jada generaator arvutab jĂ€rgmise vÀÀrtuse ainult siis, kui `next()` kutsutakse.
- Ăhilduvus: Iteraatorid töötavad sujuvalt koos teiste JavaScripti funktsioonidega, nagu laialilaotamise sĂŒntaks ja destruktureerimine.
Iteraatorite edasijÔudnud tehnikad
Iteraatorite kombineerimine
Saate kombineerida mitu iteraatorit ĂŒheks iteraatoriks. See on kasulik, kui peate töötlema andmeid mitmest allikast ĂŒhtsel viisil.
function* combineIterators(...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
yield item;
}
}
}
const array1 = [1, 2, 3];
const array2 = ["a", "b", "c"];
const string1 = "XYZ";
const combined = combineIterators(array1, array2, string1);
for (const value of combined) {
console.log(value); // VĂ€ljund: 1, 2, 3, a, b, c, X, Y, Z
}
Selles nĂ€ites vĂ”tab `combineIterators` funktsioon argumentidena suvalise arvu itereeritavaid objekte. See itereerib ĂŒle iga itereeritava objekti ja annab edasi iga elemendi. Tulemuseks on ĂŒksainus iteraator, mis toodab kĂ”ik vÀÀrtused kĂ”igist sisenditereeritavatest objektidest.
Iteraatorite filtreerimine ja teisendamine
Saate luua ka iteraatoreid, mis filtreerivad vÔi teisendavad teise iteraatori toodetud vÀÀrtusi. See vÔimaldab teil andmeid töödelda konveieril, rakendades igale vÀÀrtusele selle genereerimisel erinevaid toiminguid.
function* filterIterator(iterable, predicate) {
for (const item of iterable) {
if (predicate(item)) {
yield item;
}
}
}
function* mapIterator(iterable, transform) {
for (const item of iterable) {
yield transform(item);
}
}
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = filterIterator(numbers, (x) => x % 2 === 0);
const squaredEvenNumbers = mapIterator(evenNumbers, (x) => x * x);
for (const value of squaredEvenNumbers) {
console.log(value); // VĂ€ljund: 4, 16, 36
}
Siin vÔtab `filterIterator` itereeritava objekti ja predikaatfunktsiooni. See annab edasi ainult need elemendid, mille puhul predikaat tagastab `true`. `mapIterator` vÔtab itereeritava objekti ja teisendusfunktsiooni. See annab edasi iga elemendi kohta teisendusfunktsiooni rakendamise tulemuse.
Reaalse maailma rakendused
Iteraatori protokolli kasutatakse laialdaselt JavaScripti teekides ja raamistikes ning see on vÀÀrtuslik mitmesugustes reaalsetes rakendustes, eriti suurte andmehulkade vĂ”i asĂŒnkroonsete operatsioonidega tegelemisel.
- Andmetöötlus: Iteraatorid on kasulikud suurte andmehulkade tĂ”husaks töötlemiseks, kuna need vĂ”imaldavad teil töötada andmetega tĂŒkkidena, laadimata kogu andmehulka mĂ€llu. Kujutage ette suure kliendiandmeid sisaldava CSV-faili parsimist. Iteraator vĂ”imaldab teil töödelda iga rida, ilma et peaksite kogu faili korraga mĂ€llu laadima.
- AsĂŒnkroonsed operatsioonid: Iteraatoreid saab kasutada asĂŒnkroonsete operatsioonide haldamiseks, nĂ€iteks andmete hankimiseks API-st. Saate kasutada generaatorfunktsioone tĂ€itmise peatamiseks, kuni andmed on saadaval, ja seejĂ€rel jĂ€tkata jĂ€rgmise vÀÀrtusega.
- Kohandatud andmestruktuurid: Iteraatorid on hĂ€davajalikud spetsiifiliste lĂ€bimisnĂ”uetega kohandatud andmestruktuuride loomiseks. MĂ”elge puu andmestruktuurile. Saate rakendada kohandatud iteraatori puu lĂ€bimiseks kindlas jĂ€rjekorras (nt sĂŒgavuti- vĂ”i laiutiotsing).
- MĂ€nguarendus: MĂ€nguarenduses saab iteraatoreid kasutada mĂ€nguobjektide, osakeste efektide ja muude dĂŒnaamiliste elementide haldamiseks.
- Kasutajaliidese teegid: Paljud kasutajaliidese teegid kasutavad iteraatoreid komponentide tÔhusaks uuendamiseks ja renderdamiseks vastavalt alusandmete muudatustele.
Parimad praktikad
- Rakendage
Symbol.iteratorkorrektselt: Veenduge, et teieSymbol.iteratormeetod tagastab iteraatori objekti, mis vastab iteraatori protokollile. - KĂ€sitlege
donelippu tĂ€pselt:donelipp on iteratsiooni lĂ”pu tĂ€histamiseks ĂŒlioluline. Veenduge, et seate selle omanext()meetodis Ă”igesti. - Kaaluge generaatorfunktsioonide kasutamist: Generaatorfunktsioonid pakuvad lĂŒhemat ja loetavamat viisi iteraatorite loomiseks.
- VÀltige kÔrvalmÔjusid
next()meetodis:next()meetod peaks peamiselt keskenduma jÀrgmise vÀÀrtuse hankimisele ja iteraatori oleku vÀrskendamisele. VÀltige keeruliste operatsioonide vÔi kÔrvalmÔjude teostamistnext()sees. - Testige oma iteraatoreid pÔhjalikult: Testige oma kohandatud iteraatoreid erinevate andmehulkade ja stsenaariumidega, et tagada nende korrektne kÀitumine.
KokkuvÔte
JavaScripti iteraatori protokoll pakub vĂ”imsat ja paindlikku viisi andmestruktuuride lĂ€bimiseks. MĂ”istes itereeritava ja iteraatori protokolle ning kasutades Ă€ra generaatorfunktsioone, saate luua kohandatud iteraatoreid, mis on kohandatud teie spetsiifilistele vajadustele. See vĂ”imaldab teil tĂ”husalt andmetega töötada, parandada koodi loetavust ja suurendada oma rakenduste jĂ”udlust. Iteraatorite valdamine avab sĂŒgavama arusaama JavaScripti vĂ”imalustest ja annab teile vĂ”ime kirjutada elegantsemat ja tĂ”husamat koodi.